class MyPromise {
  static PENDING = "pending"
  static FULFILLED = "fulfilled"
  static REJECTED = "rejected"
  PromiseState = PENDING
  PromiseResult = null
  //保存两组回调函数
  fulfiledCbs = []
  rejectedCbs = []
  constructor(executor) {
    try {
      executor(this.resolve.bind(this), this.reject.bind(this))
    } catch (err) {
      this.reject(err)
    }
  }
  resolve(result) {
    if (this.PromiseState !== PENDING) return
    this.PromiseState = FULFILLED
    this.PromiseResult = result
    while (this.fulfiledCbs.length) {
      //如果成功了看回调数组里面有没有函数 如果有就依次执行
      this.fulfiledCbs.shift()()
    }
  }
  reject(reason) {
    if (this.PromiseState !== PENDING) return
    this.PromiseState = REJECTED
    this.PromiseResult = reason
    while (this.rejectedCbs.length) {
      this.rejectedCbs.shift()()
    }
  }
  /*
  如果是pending  暂时保存两个回调
  then方法本身会返回一个新的promise对象
  该对象的状态和结果由回调函数的返回值决定
  如果返回值是promise对象
    返回值为成功，新promise就是成功
    返回值为失败，新promise就是失败
  如果返回值非promise对象
    新的promise就是成功，她的值就是返回值
    */
  then(onFulfilled, onRejected) {
    //判断传进来的是不是一个函数 如果不是 成功直接返回val  失败抛出reason
    onFulfilled =
      typeof onFulfilled === "function" ? onFulfilled : (result) => result
    onRejected =
      typeof onRejected === "function"
        ? onRejected
        : (reason) => {
            throw reason
          }
    const thenPromise = new MyPromise((resolve, reject) => {
      const resolvePromise = (cb) => {
        queueMicrotask(() => {
          //添加异步因为 thenPromise 还未生成
          try {
            let x = cb(this.PromiseResult)
            if (x === thenPromise) {
              throw new Error("不能返回自身...")
            }
            if (x instanceof MyPromise) {
              x.then(resolve, reject)
            } else {
              resolve(x)
            }
          } catch (err) {
            reject(err)
          }
        })
      }
      if (this.PromiseState === FULFILLED) {
        resolvePromise(onFulfilled)
      } else if (this.PromiseState === REJECTED) {
        resolvePromise(onRejected)
      } else if (this.PromiseState === PENDING) {
        //如果不确定先保存回调
        this.fulfiledCbs.push(resolvePromise.bind(this, onFulfilled))
        this.rejectedCbs.push(resolvePromise.bind(this, onRejected))
      }
    })
    return thenPromise
  }

  static all(arr) {
    const res = []
    return new MyPromise((resolve, reject) => {
      const addData = (index, val) => {
        res[index] = val
        if (res.length == arr.length) {
          resolve(res)
        }
      }
      arr.forEach((item, index) => {
        if (item instanceof MyPromise) {
          item.then((val) => addData(index, val), reject)
        } else {
          addData(index, item)
        }
      })
    })
  }
  //数组中的常量 被视为成功的promise
  static race(arr) {
    return new MyPromise((resolve, reject) => {
      arr.forEach((item) => {
        if (item instanceof MyPromise) {
          item.then(resolve, reject)
        } else {
          queueMicrotask(() => {
            //把字面量变为微任务
            resolve(item)
          })
        }
      })
    })
  }
  //参数成功或者非promise对象  返回 成功的promise  参数为失败返回失败的promise
  static resolve() {
    if (val instanceof MyPromise) return val
    return new MyPromise((resolve) => resolve(val))
  }
  //参数为成功的promise 会被包裹为失败的promise对象
  static reject(param) {
    return new MyPromise((resolve, reject) => param)
  }
  static finally(callback) {
    this.then(callback, callback).then(
      () => this,
      (err) => {
        throw err
      }
    )
  }
  catch(onRejected) {
    return this.then(null, onRejected)
  }
}
